using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using OFX.Aggregator.Infrastructure;

namespace OFX.Aggregator.Implementation.Retrieval
{
	public class HtmlClipboardStatementRetrieval : IStatementRetrieval
	{
		private readonly IStatementInterpreter interpreter;

		public HtmlClipboardStatementRetrieval(IStatementInterpreter interpreter)
		{
			this.interpreter = interpreter;
		}

		#region IStatementRetrieval Members

		public bool CanRetrieveStatement
		{
			get { return Clipboard.ContainsText(TextDataFormat.Html); }
		}

		public Statement GetStatement(DateTime? dateStart, DateTime? dateEnd)
		{
			Statement statement = null;

			if (CanRetrieveStatement)
			{
				string html = GetHtmlFromClipboard();

				Debug.Assert(!string.IsNullOrEmpty(html));

				if (!string.IsNullOrEmpty(html))
				{
					int startFragmentIndex = html.IndexOf("<!--StartFragment-->");
					int endFragmentIndex = html.IndexOf("<!--EndFragment-->");
					html = html.Substring(startFragmentIndex, endFragmentIndex - startFragmentIndex);

					statement = this.interpreter.InterpretStatement(html);

					StatementFilter.Filter(statement, dateStart, dateEnd);
				}
			}

			return statement;
		}

		#endregion

		[DllImport("user32.dll", SetLastError = true)]
		private static extern IntPtr GetClipboardData(uint uFormat);

		[DllImport("user32.dll", SetLastError = true)]
		private static extern bool OpenClipboard(Form hWndNewOwner);

		[DllImport("user32.dll", SetLastError = true)]
		private static extern bool CloseClipboard();

		[DllImport("user32.dll", SetLastError = true)]
		private static extern uint RegisterClipboardFormatA(string lpszFormat);

		[DllImport("user32.dll", SetLastError = true)]
		private static extern bool IsClipboardFormatAvailable(uint format);

		[DllImport("kernel32.dll", SetLastError = true)]
		private static extern IntPtr GlobalLock(IntPtr hMem);

		[DllImport("kernel32.dll", SetLastError = true)]
		private static extern uint GlobalSize(IntPtr hMem);

		[DllImport("kernel32.dll", SetLastError = true)]
		private static extern IntPtr GlobalUnlock(IntPtr hMem);

		private static string GetHtmlFromClipboard()
		{
			string html = string.Empty;
			//Form activeForm = Application.OpenForms[0];
			//Debug.Assert(activeForm != null);

			if (OpenClipboard(null))
			{
				uint CF_HTML = RegisterClipboardFormatA("HTML Format");
				IntPtr hGMem = GetClipboardData(CF_HTML);
				IntPtr pMFP = GlobalLock(hGMem);
				uint len = GlobalSize(hGMem);
				var bytes = new byte[len];
				Marshal.Copy(pMFP, bytes, 0, (int) len);

				html = Encoding.UTF8.GetString(bytes);
				GlobalUnlock(hGMem);
				CloseClipboard();
			}
			else
			{
				Debug.Fail("Could not open clipboard!");
			}

			return html;
		}
	}
}